﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;

namespace orit120132
{
    class TabelaHash
    {
        List<Termo>[] Tabela;
        List<string>[] Palavras;
        string local;

        public TabelaHash(int tamanho, string local)
        {
            Tabela = new List<Termo>[tamanho];
            Palavras = new List<string>[tamanho];
            this.local = local;

            for (int i = 0; i < tamanho; i++)
            {
                Tabela[i] = new List<Termo>();
                Palavras[i] = new List<string>();
            }
            if (System.IO.File.Exists(local))
                ConsultaXML();
        }

        public int FuncaoHash(string palavra)
        {
            int valor = 0, i;
            for (i = 0; i < palavra.Length; i++)
            {
                valor += (int)palavra[i];
            }
            valor = valor % Tabela.Length;
            return valor;
        }

        public bool Contem(string palavra)
        {
            for (int i = 0; i < Palavras.Length; i++)
            {
                foreach (string x in Palavras[i])
                {
                    if (x == palavra)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        public bool Inserir(string palavra, Termo termo)
        {
            int hash = FuncaoHash(palavra);

            if (!Contem(palavra))
            {
                Palavras[hash].Add(palavra);
                Tabela[hash].Add(termo);
                return true;
            }
            return false;
        }


        public bool Remover(string palavra)
        {
            int hash = FuncaoHash(palavra);
            int indice = Palavras[hash].IndexOf(palavra);
            if (indice != -1)
            {
                Palavras[hash].RemoveAt(indice);
                Tabela[hash].RemoveAt(indice);
                if (System.IO.File.Exists(local))
                    RemoveXML(palavra);
                return true;
            }
            return false;
        }

        public Termo Buscar(string palavra)
        {
            int hash = FuncaoHash(palavra);
            int indice = Palavras[hash].IndexOf(palavra);
            if (indice != -1)
            {
                return Tabela[hash].ElementAt(indice);
            }
            return null;
        }

        public void CriaXML()
        {
            XmlTextWriter escritor = new XmlTextWriter(local, null);
            escritor.Formatting = Formatting.Indented;

            escritor.WriteStartDocument();
            escritor.WriteStartElement("Lista");
            escritor.WriteEndElement();
            escritor.WriteEndDocument();
            escritor.Close();
        }

        public void InsereXML()
        {
            XElement file = XElement.Load(local);
            string funcionaPorFavor;

            for (int i = 0; i < Palavras.Length; i++)
            {
                foreach (string x in Palavras[i])
                {
                    foreach (Termo y in Tabela[i])
                    {
                        if (!PossuiPalavra(x))
                        {
                            funcionaPorFavor = string.Empty;
                            for (int j = 0; j < y.Significados().Length; j++)
                                funcionaPorFavor += y.Significados()[j] + "¬";

                            funcionaPorFavor = funcionaPorFavor.Substring(0, funcionaPorFavor.Length - 1);
                            XElement xml = new XElement("Palavra", new XAttribute("value", x), new XElement("Significados", funcionaPorFavor));
                            file.Add(xml);
                            file.Save(local);
                        }
                    }
                }
            }
        }

        private void ConsultaXML()
        {
            XmlDocument doc = new XmlDocument();
            Termo termoAux;


            doc.Load(local);

            XmlNodeList pal = doc.GetElementsByTagName("Palavra");
            XmlNodeList sign = doc.GetElementsByTagName("Significados");

            for (int i = 0; i < pal.Count; i++)
            {
                //separa a string com os significados em um conjunto de 5 strings
                string aux = sign.Item(i).InnerText;
                String[] significados = aux.Split(new char[] { '¬' });

                termoAux = new TermoDicionario();
                //Insere o conjunto de significados em um objeto Termo
                termoAux.Inserir(significados);
                //Insere a palavra e o termo
                this.Inserir(pal.Item(i).Attributes.GetNamedItem("value").InnerText, termoAux);
            }
        }

        public bool PossuiPalavra(string palavra)
        {
            XmlDocument doc = new XmlDocument();

            doc.Load(local);

            XmlNodeList pal = doc.GetElementsByTagName("Palavra");

            for (int i = 0; i < pal.Count; i++)
            {
                if (pal.Item(i).Attributes.GetNamedItem("value").InnerText == palavra)
                    return true;
            }
            return false;
        }

        private void RemoveXML(string palavra)
        {
            XDocument xdoc = XDocument.Load(local);

            var matchingElements = xdoc.Root.Descendants("Palavra").Where(e => (string)e.Attribute("value") == palavra).ToList();
            foreach (var elem in matchingElements)
            {
                matchingElements.Remove();
            }

            xdoc.Save(local);
        }
    }
}
